package com.zll.shirotest.config;

import com.zll.shirotest.shiro.RedisSessionDao;
import com.zll.shirotest.shiro.UserAuthorizingRealm;
import com.zll.shirotest.shiro.ShiroSessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Value("${shiro.session.redis.expireTime}")
    private long expireTime;

    /**
     * 讲自定义的sessionmanager加入容器
     * @return
     */
    @Bean
    public ShiroSessionManager shiroSessionManager(RedisSessionDao redisSessionDao) {
        ShiroSessionManager shiroSessionManager = new ShiroSessionManager();
        //这里sessionDao可改为redis的实现
        shiroSessionManager.setSessionDAO(redisSessionDao);
        //设置session过期时间
        shiroSessionManager.setGlobalSessionTimeout(expireTime * 1000);
        //删除失效的session
        shiroSessionManager.setDeleteInvalidSessions(true);
        //设置会话验证器（默认就是开启的）
//        shiroSessionManager.setSessionValidationSchedulerEnabled(true);
        //设置session过期监听(集成sessionlistener)
//        shiroSessionManager.setSessionListeners();
        return shiroSessionManager;
    }

    /**
     * securityManager
     * @param userAuthorizingRealm
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager(UserAuthorizingRealm userAuthorizingRealm,ShiroSessionManager shiroSessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userAuthorizingRealm);
        //放入重写的sessionmanager（重写获取sessionid的逻辑还可以设置sessionDao的自定义实现）
        securityManager.setSessionManager(shiroSessionManager);
//        securityManager.setRememberMeManager(null);
        //可防止每次请求都进行权限授权可以使用redis
//        securityManager.setCacheManager(null);
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        //设置未认证跳转页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        //设置无权限跳转页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
        //配置拦截规则
        Map<String, String> filterMap = new LinkedHashMap<>();
        //登录和注册不需要验证
        filterMap.put("/login", "anon");
        filterMap.put("/registry", "anon");
        //api打头的都需要验证
        filterMap.put("/api/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }


    //增加注解权限控制支持
    /*
    @RequiresRoles和@RequiresPermissions
    两个参数：value是必须的，可以传入一个字符数组，表示一个或多个角色（权限）
            logical有两个值可选，AND 和 OR，默认为 AND
     */

    /**
     * 相当于切面
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    /**
     * 相当于切点
     * @param defaultWebSecurityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
        return authorizationAttributeSourceAdvisor;
    }

}
